package ling.archives.service;

import com.easy.query.core.api.pagination.EasyPageResult;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import ling.archives.common.DataUtil;
import ling.archives.common.EQueryService;
import ling.archives.common.domain.PageSort;
import ling.archives.common.domain.Result;
import ling.archives.common.domain.ResultRows;
import ling.archives.domain.ApprovalRecord;
import ling.archives.domain.Archive;
import lombok.Data;
import lombok.var;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Objects;
import java.util.stream.Collectors;

@Data
@Service
public class ApprovalService extends EQueryService<ApprovalRecord> {
    @Data
    public static class IApprovalInfo{
        String approvalStatus;
        String approvalRecord;
    }
    //建草稿，提交，获取，审批

    public ResultRows<ApprovalRecord> approvalList(ApprovalRecord dto, PageSort pageSort) {
        var loginUser= SecurityUtils.getLoginUser().getUser();
        var userId = loginUser.getUserId();
        var roles = loginUser.getRoles().stream().map(p -> p.getRoleKey()).toArray(String[]::new);
        var page = queryHelper.entityQuery(ApprovalRecord.class)
                .where(a -> {
                    a.flowId().gt(0l);
                    //a.status().eq(ApprovalRecord.StatusWait);
                    a.or(() -> {
                        a.approver().eq(userId + "");
                        a.nodeRole().in(roles);
                    });
                }).whereObject(dto).orderBy(p -> p.createdTime().desc())
                .orderByObject(pageSort)
                .toPageResult(pageSort.getPageNum(), pageSort.getPageSize());
        return  new ResultRows<>(page.getTotal(),page.getData());
    }
    public Result<Long> createWF(String tmplType,String title,String formData,String remark) {
        var entity=new ApprovalRecord();
        entity.setFlowTitle(title);
        entity.setFormData(formData);
        entity.setFlowType(tmplType);
        //
        var wf = DictUtils.getDictCache(entity.getFlowType());
        var roleList = wf.stream().map(p -> p.getDictValue()).collect(Collectors.toList());
        entity.setBody(DataUtil.toJson(roleList));
        entity.setFlowId(0l);
        entity.setStatus(ApprovalRecord.StatusDraft);
        //
        var loginUser= SecurityUtils.getLoginUser().getUser();
        entity.setType("table");
        entity.setCreatedId(loginUser.getUserId());
        entity.setName(loginUser.getNickName());
        entity.setCreatedTime(new Date());
        entity.setRemark(remark);

        queryHelper.entityQuery().insertable(entity).executeRows(true);
        //执行流程，创建第一个节点审批记录
        var node = sendNext(entity,null);
        return Result.ok(node.getId());
    }
    /** 审批,返回流程状态
     *
     * @param nodeId
     * @param isPass
     * @param remark
     */
    @Transactional
    public Result<ApprovalRecord> Approval(Long nodeId, boolean isPass, String remark) {
       var loginUser= SecurityUtils.getLoginUser().getUser();
        var node = queryHelper.entityQuery(ApprovalRecord.class).whereById(nodeId).firstOrNull();
        var isRole= loginUser.getRoles().stream().anyMatch(p-> Objects.equals(p.getRoleKey(), node.getNodeRole()));
        if(!isRole)
            return Result.bad("无权审批");
        node.setApprover(loginUser.getUserId() + "");
        node.setName(loginUser.getNickName());
        node.setRemark(remark);
        node.setApprovalTime(new Date());
        var main=queryHelper.entityQuery(ApprovalRecord.class).whereById(node.getFlowId()).firstOrNull();
        main.setApprovalTime(new Date());
        main.setRemark(remark);
        if (isPass) {
            node.setStatus(ApprovalRecord.StatusPass);
            main.setStatus(ApprovalRecord.StatusPass);
            queryHelper.entityQuery().updatable(node).executeRows();
            queryHelper.entityQuery().updatable(main).executeRows();
            //执行下个节点
            sendNext(main, node);
            return Result.ok(main);
        }
        node.setStatus(ApprovalRecord.StatusReject);
        main.setStatus(ApprovalRecord.StatusReject);
        queryHelper.entityQuery().updatable(node).executeRows();
        queryHelper.entityQuery().updatable(main).executeRows();
        return Result.ok(main);
    }
    /** 推进到下个节点，如果已结束返回null,否则返回新节点
     *
     * @param entity
     * @param oldNode
     * @return 新节点
     */
    ApprovalRecord sendNext(ApprovalRecord entity,ApprovalRecord oldNode) {
        var roleArr = DataUtil.toObjByJson(entity.getBody(), String[].class);
        var loginUser= SecurityUtils.getLoginUser().getUser();
        var node = new ApprovalRecord();
        node.setFlowId(entity.getId());
        node.setFlowTitle(entity.getFlowTitle());
        node.setFlowType(entity.getFlowType());
        node.setType("1");
        node.setStatus(ApprovalRecord.StatusWait);
        node.setCreatedTime(new Date());
        node.setCreatedId(loginUser.getUserId());
        node.setFormData(entity.getFormData());
        if (oldNode == null) {
            entity.setStatus(ApprovalRecord.StatusWait);
            //
            node.setBody("1");
            node.setNodeRole(roleArr[0]);
            queryHelper.entityQuery().insertable(node).executeRows(true);
            queryHelper.entityQuery().updatable(entity).executeRows();
            return node;
        }
        var index=Integer.parseInt(oldNode.getBody());
        if(index>=roleArr.length) {
            //结束
            entity.setStatus(oldNode.getStatus());
            entity.setApprovalTime(new Date());
            queryHelper.entityQuery().updatable(entity);
            return null;
        }
        node.setBody((index+1)+"");
        node.setNodeRole(roleArr[index]);
        entity.setStatus(ApprovalRecord.StatusInProgress);
        queryHelper.entityQuery().insertable(node).executeRows(true);
        queryHelper.entityQuery().updatable(entity).executeRows();
        var nodeId = node.getId();  // 这个ID已经有了，不需要查询数据库

// 直接更新档案
        var ids = DataUtil.toObjByJson(entity.getFormData(), Long[].class);
        var archives = queryHelper.entityQuery(ling.archives.domain.Archive.class).where(a -> a.id().in(ids)).toList();
        archives.forEach(p -> p.setApprovalId(nodeId.intValue()));
        queryHelper.entityQuery().updatable(archives).executeRows();
        return node;
    }
}
